import Color from './color';
import Layout from './layout';

function createPrinter(context, b43) {
  return {

    zrender : null,
    zr : null,
    require : ['zrender'],
    width : 1920,
    height : 1080,
    arg : {
      // 当前 style
      style : 'dark',
      leftStyle : 'dark',
      rightStyle : 'dark',
  
      // p1 + p2
      p1Name : '1P',
      p2Name : '2P',
  
      // 计时器状态
      baseTime : null, // 开始的时间. 按照现在的时间减去计时器数值得到的时间
      // 计时器是否正在运行.
      // 暂停时也为 true, 重置或者在 0 时刻还未启动时为 false
      playing : false,
      // 是否在暂停. 暂停则为现在计时器的时间值, 单位毫秒
      pause : 0,
      p1Score : 0, // 大于零就是说 p1 完成了, 否则就是 0
      p2Score : 0
    },

    sprites : {
      // 框线 size:2
      screenStrokes : [],
  
      // belt
      belt : null,
      beltUpdater : null, // 更新时用
      beltFlashLeft : null, // 动画的白闪效果, 左半部
      beltFlashRight : null, // 动画的白闪效果, 右半部
      // 文字
      beltP1 : null,
      beltP2 : null,
      // 两边记时间的, 背景
      beltLeftChunk : null,
      beltRightChunk : null,
      // 两边记时间的, 文字
      beltLeftTime : null,
      beltRightTime : null,
      // 中间计时器的六角形
      beltHexagon : null,
      beltHexagonUpdater : null, // 更新时用
      beltHexagonFlash : null, // 动画的白闪效果
      // 计时器里面的数字, 共十个数字
      // 0: 分秒
      // 1: 小数点
      // 2: 秒 个位
      // 3: 秒 十位
      // 4: 冒号
      // 5: 分 个位
      // 6: 分 十位
      // 7: 冒号
      // 8: 时 个位
      // 9: 时 十位
      beltTimerFigures : [],
  
      shapeHexagon : null, // 这个是 ZRender 形状
      spriteFigures : null // 这个是 Image
    },

    handler : {
      // 计时器的
      timer : null
    },

    pendants : {
      background : null
    },

    /** @type {Color} */
    color : new Color(),
    /** @type {Layout} */
    layout : new Layout(b43),

    init(libs) {
      this.zrender = libs.zrender;
      
      handleDom(this.width, this.height);
      this.zr = libs.zrender.init(document.getElementById('content'));

      // 挂件
			this.loadBackground();
			// end
			this.initAssets();
			// **** 绘画部分
	
			// 中间那条线
			this.createBelt();
			// // 主屏幕
			this.createScreen();
			// // 底
			this.createBottom();

    },

    collectInfo() {
      return this.arg;
    },
  
    initAssets() {
      // 使用 DOM HTMLImageElement
      let img = this.sprites.spriteFigures = document.createElement('img');
      img.src = context.assetPath('img/figures.png');
    },

    /* **********
     *   挂件   *
     ********** */
    loadBackground () {
      let self = this;
      return context.createPendant('board_2018/background', {
        width: this.width,
        height: this.height,
        dom : 'background',
        layout: self.layout,
        color: self.color,
      }).then(function (background) {
        self.pendants.background = background;
      });
    },

    /* **********
     *   展示   *
     ********** */

    /**
     * 更新 style. style 是 'dark' 或 'light'
     * 状态改变不在这个方法
     */
    updateBgStyle(style) {
      if (this.pendants.background) {
        this.pendants.background.updateBgStyle(style);
      }
    },

    createScreen() {
      screenZrenderNode(this.layout, this.color, this.zrender)
        .forEach((elem, i) => {
          this.sprites.screenStrokes[i] = elem;
          this.zr.add(elem);
        })
    },

    createBelt() {
      let canvasWidth = this.width;
      let {layout, color, zrender, zr} = this;

      let colors = this.color[this.arg.style];
      let self = this;

      zr.add(this.sprites.belt
        = screenBelt(layout, color, zrender, this.arg.leftStyle, this.arg.rightStyle, canvasWidth));

      zr.add(screenBeltA(layout, zrender, canvasWidth));

      let array = screenBeltFlash(layout, zrender, canvasWidth);
      zr.add(this.sprites.beltFlashLeft = array[0]);
      zr.add(this.sprites.beltFlashRight = array[1]);

      // 文字
      array = screenBeltText(layout, zrender, canvasWidth, 
        [this.arg.p1Name, this.arg.p2Name]);
      zr.add(this.sprites.beltP1 = array[0]);
      zr.add(this.sprites.beltP2 = array[1]);

      // 两边记时间的, 背景
      array = screenBeltRecordChunk(layout, zrender, canvasWidth);
      zr.add(this.sprites.beltLeftChunk = array[0]);
      zr.add(this.sprites.beltRightChunk = array[1]);

      // 两边记时间的, 文字
      array = screenBeltRecordText(layout, zrender, canvasWidth);
      zr.add(this.sprites.beltLeftTime = array[0]);
      zr.add(this.sprites.beltRightTime = array[1]);

      // 先把中间那个六角形图形存起来
      let shapeHexagon = this.sprites.shapeHexagon = createShapeHexagon(zrender);
      zr.add(this.sprites.beltHexagon
        = screenBeltHexagon(layout, color, zrender, shapeHexagon, this.arg.style, canvasWidth));

      zr.add(this.sprites.beltHexagonFlash
        = screenBeltHexagonFlash(layout, shapeHexagon, canvasWidth));

      // 数字
      for (let i = 0; i < 10; i ++) {
        let ch = 0;
        switch (i) {
          case 1: ch = '.'; break;
          case 4: case 7: ch = ':'; break;
        }
        zr.add(this.sprites.beltTimerFigures[i]
          = buildFigures(zrender, this.sprites.spriteFigures, ch, canvasWidth, this.height,
            this.arg.style, i < 2, null));
      }
      
      this.handler.timer = setInterval(() => {
        self.updateTimerFigures();
      }, 1000 / 30);
    },

    updateTimerFigures() {
      let time = 0;
      if (this.arg.playing) {
        if (this.arg.pause) {
          time = this.arg.pause;
        } else {
          time = new Date().getTime() - this.arg.baseTime;
        }
      }

      this.buildTimerFigures(toTimeArray(time));
    },

    /**
     * 更新 belt
     */
    updateBeltStyle (leftStyle, rightStyle, leftFlash = false, rightFlash = false) {
      let {zrender, zr, color, layout} = this;
      let canvasWidth = this.width;

      if (this.sprites.beltUpdater != null) {
        zr.remove(this.sprites.belt);
        this.sprites.belt.stopAnimation(true);
        this.sprites.beltUpdater.stopAnimation(true);
        this.sprites.belt = this.sprites.beltUpdater;
        this.sprites.beltUpdater = null;
      }

      let self = this;
      if (leftFlash && rightFlash) {
        // 直接替换
        zr.remove(this.sprites.belt);
        zr.add(this.sprites.belt = screenBelt(layout, color, zrender,
          leftStyle, rightStyle, canvasWidth));
      } else {
        zr.add(this.sprites.beltUpdater = screenBelt(layout, color, zrender,
          leftStyle, rightStyle, canvasWidth, 0));
        this.sprites.beltUpdater.animate('style', false)
          .when(1000, {opacity:1})
          .done(function () {
            self.zr.remove(self.sprites.belt);
            self.sprites.belt = self.sprites.beltUpdater;
            self.sprites.beltUpdater = null;
          })
          .start('cubicInOut');
        this.sprites.belt.animate('style', false)
          .when(900, {opacity:0})
          .start('cubicInOut');
      }

      if (leftFlash) {
        let flash = this.sprites.beltFlashLeft;
        flash.attr({style: {opacity:1}});
        flash.animate('style', false)
          .when(2500, {opacity:0})
          .start('cubicInOut');
      }
      if (rightFlash) {
        let flash = this.sprites.beltFlashRight;
        flash.attr({style: {opacity:1}});
        flash.animate('style', false)
          .when(2500, {opacity:0})
          .start('cubicInOut');
      }

      if (this.arg.p1Score) {
        // 左边计时文本
        this.sprites.beltLeftChunk.attr({style:{opacity:1}});
        this.sprites.beltLeftTime.attr({style:{opacity:1,text:toTimeText(this.arg.p1Score)}});
      } else {
        this.sprites.beltLeftChunk.attr({style:{opacity:0}});
        this.sprites.beltLeftTime.attr({style:{opacity:0,text:''}});

      }
      if (this.arg.p2Score) {
        // 右边计时文本
        this.sprites.beltRightChunk.attr({style:{opacity:1}});
        this.sprites.beltRightTime.attr({style:{opacity:1,text:toTimeText(this.arg.p2Score)}});
      } else {
        this.sprites.beltRightChunk.attr({style:{opacity:0}});
        this.sprites.beltRightTime.attr({style:{opacity:0,text:''}});
      }
    },

    /**
     * 更新计时器的底
     */
    updateHexagonStyle (style, hexagonFlash) {
      if (this.sprites.beltHexagonUpdater != null) {
        this.zr.remove(this.sprites.beltHexagon);
        this.sprites.beltHexagon.stopAnimation(true);
        this.sprites.beltHexagonUpdater.stopAnimation(true);
        this.sprites.beltHexagon = this.sprites.beltHexagonUpdater;
        this.sprites.beltHexagonUpdater = null;
      }

      let self = this;

      if (hexagonFlash) {
        // 不用替换了
        this.zr.remove(this.sprites.beltHexagon);
        this.zr.add(this.sprites.beltHexagon = screenBeltHexagon(this.layout, this.color, this.zrender,
          this.sprites.shapeHexagon, style, this.width));
      } else {
        this.zr.add(this.sprites.beltHexagonUpdater = screenBeltHexagon(this.layout, this.color, this.zrender,
          this.sprites.shapeHexagon, style, this.width, 0));
        this.sprites.beltHexagonUpdater.animate('style', false)
          .when(1000, {opacity:1})
          .done(function () {
            self.zr.remove(self.sprites.beltHexagon);
            self.sprites.beltHexagon = self.sprites.beltHexagonUpdater;
            self.sprites.beltHexagonUpdater = null;
          })
          .start('cubicInOut');
        this.sprites.beltHexagon.animate('style', false)
          .when(900, {opacity:0})
          .start('cubicInOut');
      }

      if (hexagonFlash) {
        let flash = this.sprites.beltHexagonFlash;
        flash.attr({style: {opacity:0.8}});
        flash.animate('style', false)
          .when(2500, {opacity:0})
          .start('cubicInOut');
      }
    },

    updateStyle (style, leftStyle, rightStyle, hexagonFlash = false, leftFlash = false, rightFlash = false) {
      if (style != this.arg.style) {
        this.updateBgStyle(style);
        this.updateHexagonStyle(style, hexagonFlash);
      }

      if (leftStyle != this.arg.leftStyle || rightStyle != this.arg.rightStyle) {
        this.updateBeltStyle(leftStyle, rightStyle, leftFlash, rightFlash);
      }

      this.arg.style = style;
      this.arg.leftStyle = leftStyle;
      this.arg.rightStyle = rightStyle;

      // 发送
      this.sendStatus();
    },

    /**
     * 写计时器数据, 画上去
     * period 指的是 ds 往上, 一共有多少数字
     */
    buildTimerFigures (figures) {
      let {zrender} = this;
      let shape = this.sprites.spriteFigures;

      let width = 0;
      switch (figures.length) {
        case 3: width = 108; break; // 36*2 + 12+24
        case 4: width = 168; break; // 36 + 24 + 36*2 + 12+24
        case 5: width = 204; break; // 36*2 + 24 + 36*2 + 12+24
        case 6: width = 264; break; // 36 + 24 + 36*2 + 24 + 36*2 + 12+24
        case 7: width = 300; break; // 36*2 + 24 + 36*2 + 24 + 36*2 + 12+24
      }

      let xend = this.width / 2 + width / 2;
      let ystart = this.layout.bgMoverOriY + 15;

      // 从右边开始放
      // ds
      let ds = figures[0];
      let x = xend - 24;
      buildFigures(zrender, shape, ds, x, ystart + 12, this.arg.style, true, this.sprites.beltTimerFigures[0]);
      // 小数点
      x = x - 12;
      buildFigures(zrender, shape, '.', x, ystart + 12, this.arg.style, true, this.sprites.beltTimerFigures[1]);
      // s
      x = x - 36;
      buildFigures(zrender, shape, figures[1], x, ystart, this.arg.style, false, this.sprites.beltTimerFigures[2]);
      x = x - 36;
      buildFigures(zrender, shape, figures[2], x, ystart, this.arg.style, false, this.sprites.beltTimerFigures[3]);
      if (figures.length == 3) {this.hideFigures(4); return;}
      // 冒号
      x = x - 24;
      buildFigures(zrender, shape, ':', x, ystart, this.arg.style, false, this.sprites.beltTimerFigures[4]);
      x = x - 36;
      buildFigures(zrender, shape, figures[3], x, ystart, this.arg.style, false, this.sprites.beltTimerFigures[5]);
      if (figures.length == 4) {this.hideFigures(6); return;}
      x = x - 36;
      buildFigures(zrender, shape, figures[4], x, ystart, this.arg.style, false, this.sprites.beltTimerFigures[6]);
      if (figures.length == 5) {this.hideFigures(7); return;}
      // 冒号
      x = x - 24;
      buildFigures(zrender, shape, ':', x, ystart, this.arg.style, false, this.sprites.beltTimerFigures[7]);
      x = x - 36;
      buildFigures(zrender, shape, figures[5], x, ystart, this.arg.style, false, this.sprites.beltTimerFigures[8]);
      if (figures.length == 6) {this.hideFigures(9); return;}
      x = x - 36;
      buildFigures(zrender, shape, figures[6] % 10, x, ystart, this.arg.style, false, this.sprites.beltTimerFigures[9]);
    },

    hideFigures (startIndex) {
      for (let i = startIndex; i < this.sprites.beltTimerFigures.length; i++) {
        this.sprites.beltTimerFigures[i].attr({
          style : {
            opacity: 0
          }
        });
      }
    },

    /**
     * 底部分
     */
    createBottom () {
      let h = this.layout.bottomHeight;

      // 白线
      this.zr.add(new this.zrender.Line({
        shape: {
          x1: 0, y1: 999,
          x2: this.width, y2: 999,
        },
        style: {
          stroke: '#FFF',
          opacity: 1
        },
        position: [0, 0],
        z: 11
      }));

      // 底
      this.zr.add(new this.zrender.Rect
      ({
        shape: {
          width: this.width,
          height: h
        },
        style: {
          fill: new this.zrender.LinearGradient(
            0, 0, 0, 1,
            [
              {offset:0, color:'#FFF'},
              {offset:0.04, color:'#444'},
              {offset:0.86, color:'#222'}
            ]
          ),
          opacity: 0.6
        },
        position: [0, 1000],
        z: 11
      }));
    },
    
    /* **********
     * 状态控制 *
     ********** */

    /*
     * 命令: 文本改变
     * name = 'player_name_change'
     * arg = 
     * 
     * 命令: 计时器命令: 开始  style=light,light,light  计时器启动效果 玩家启动效果
     * name = 'timer_start'
     * arg = 
     * 
     * 命令: 计时器命令: 结束  style=ori,ori,ori  玩家无结束效果
     * name = 'timer_stop'
     * arg = 
     * 
     * 命令: 计时器命令: 暂停  style=ori,ori,ori  玩家无结束效果
     * name = 'timer_pause'
     * arg = 
     * 
     * 命令: 计时器命令: 重置  style=dark,dark,dark  无效果
     * name = 'timer_reset'
     * arg = 
     * 
     * 命令: 计时器命令: 撤销暂停  style=light,light,light  无效果
     * name = 'timer_undoPause'
     * arg = 
     * 
     * 命令: 计时器命令: 记录  style=dark/ori,dark/ori,dark/ori  玩家结束效果
     * name = 'timer_record'
     * arg = {player : 1|2}
     * 
     * 命令: 计时器命令: 撤销记录  style=light,light,light  无效果
     * name = 'timer_undoRecord'
     * arg = 
     * 
     */
    onMessage (name, arg) {
      console.log("board_43 收到命令: " + name);
  //		console.log(arg);
      switch (name) {
        case 'player_name_change': // 文本改变
        this.playerNameChange(arg);
        break;
        case 'timer_start': // 计时器
        this.timerStart();
        break;
        case 'timer_stop': // 计时器
        this.timerStop();
        break;
        case 'timer_pause': // 计时器
        this.timerPause();
        break;
        case 'timer_reset': // 计时器
        this.timerReset();
        break;
        case 'timer_undoPause': // 计时器
        this.timerUndoPause();
        break;
        case 'timer_record': // 计时器
        this.timerRecord(arg);
        break;
        case 'timer_undoRecord': // 计时器
        this.timerUndoRecord(arg);
        break;
      }
    },

    playerNameChange (o) {
      if (o.p1Name != undefined) {
        this.arg.p1Name = o.p1Name;
      }
      if (o.p2Name != undefined) {
        this.arg.p2Name = o.p2Name;
      }

      this.sprites.beltP1.attr({style:{text: this.arg.p1Name}});
      this.sprites.beltP2.attr({style:{text: this.arg.p2Name}});

      this.sendStatus();
    },

    timerStart () {
      if (this.arg.playing == true && this.arg.pause == 0) {
        console.log("计时器已经启动了");
        return;
      }
      if (this.arg.playing == false) { // 从头启动
        this.arg.baseTime = new Date().getTime();
        this.arg.pause = 0;
        this.arg.playing = true;
      } else { // 从暂停启动
        this.arg.baseTime = new Date().getTime() - this.arg.pause;
        this.arg.pause = 0;
        this.arg.playing = true;
      }

      // 计时器动画
      // P1 动画
      // P2 动画
      this.updateStyle('light', (this.arg.p1Score > 0) ? 'ori' : 'light',
        (this.arg.p2Score > 0) ? 'ori' : 'light',
        true, true, true);
    },

    /*
     * 停止是带效果的暂停, 而且可以不停地按
     */
    timerStop () {
      if (this.arg.playing == false || this.arg.pause > 0) {
        console.log("计时器已暂停或还未启动");
        return;
      }
      this.arg.pause = new Date().getTime() - this.arg.baseTime;
      this.updateStyle('ori', 'ori', 'ori', true, true, true);
    },

    timerPause () {
      if (this.arg.playing == false || this.arg.pause > 0) {
        console.log("计时器已暂停或还未启动");
        return;
      }
      this.arg.pause = new Date().getTime() - this.arg.baseTime;
      this.updateStyle('ori', 'ori', 'ori');
    },

    timerReset () {
      this.arg.pause = 0;
      this.arg.playing = false;
      this.arg.baseTime = 0;

      this.arg.p1Score = 0;
      this.arg.p2Score = 0;

      this.updateStyle('dark', 'dark', 'dark');
    },

    timerUndoPause () {
      if (this.arg.pause == 0) {
        console.log("计时器已经启动了");
        return;
      }
      if (this.arg.playing == false) {
        console.log("计时器还没启动呢");
        return;
      }
      // this.arg.baseTime 不变
      this.arg.pause = 0;

      this.updateStyle('light', (this.arg.p1Score > 0) ? 'ori' : 'light',
        (this.arg.p2Score > 0) ? 'ori' : 'light');
    },

    timerRecord (o) {
      if (o.player != 1 && o.player != 2 || this.arg.baseTime == 0) {
        return;
      }
      let time = new Date().getTime() - this.arg.baseTime;
      if (this.arg.pause > 0) {
        time = this.arg.pause;
      }
      if (o.player == 1) {
        if (this.arg.p1Score == 0) {
          this.arg.p1Score = time;
          // P1 动画
        } else {
          return;
        }
      } else {
        if (this.arg.p2Score == 0) {
          this.arg.p2Score = time;
          // P2 动画
        } else {
          return;
        }
      }

      let timerFlash = false; // 计时器下面的底要不要有结束动画
      if (this.arg.p1Score > 0 && this.arg.p2Score > 0) {
        // 计时停止
        if (this.arg.pause == 0) {
          this.arg.pause = time;
          timerFlash = true;
        }
        // 计时器动画
      }

      this.updateStyle(
        (this.arg.p1Score > 0 && this.arg.p2Score > 0) ? 'ori' : 'light',
        (this.arg.p1Score > 0) ? 'ori' : 'light',
        (this.arg.p2Score > 0) ? 'ori' : 'light',
        (this.arg.p1Score > 0 && this.arg.p2Score > 0),
        (this.arg.p1Score > 0),
        (this.arg.p2Score > 0)
      );
    },

    timerUndoRecord (o) {
      // TODO 没完成
    },

    //
  };
}

function handleDom(width, height) {
  var main = document.getElementById('main');
  main.style.width = width + 'px';
  main.style.height = height + 'px';

  let childdiv = document.createElement('div');
  childdiv.id = 'background';
  childdiv.style.position = 'absolute';
  childdiv.style.width = width + 'px';
  childdiv.style.height = height + 'px';
  main.appendChild(childdiv);
  
  let contentdiv = document.createElement('div');
  contentdiv.id = 'content';
  contentdiv.style.position = 'absolute';
  contentdiv.style.width = width + 'px';
  contentdiv.style.height = height + 'px';
  main.appendChild(contentdiv);
}

/**
 * @param {Layout} layout 
 * @param {Color} color 
 */
function screenZrenderNode(layout, color, zrender) {
  return layout.screens.map((item, i) => new zrender.Rect({
    shape: {
      width: item.width,
      height: item.height
    },
    style: {
      fill: 'none',
      stroke: new zrender.LinearGradient(
        0 - i, 0.5, 0.0667 - i, 0,
        [
          {offset:0, color: color.screenStroke[0]},
          {offset:0.33, color: color.screenStroke[1]},
          {offset:0.67, color: color.screenStroke[1]},
          {offset:1, color: color.screenStroke[0]}
        ]
      ),
      lineWidth: 6,
      shadowColor: 'black',
      shadowBlur: 5,
      shadowOffsetX: 3,
      shadowOffsetY: 3
    },
    position: [item.x, item.y],
    z: 16
  }));
}

/**
 * @param {Layout} layout 
 * @param {Color} color
 * @param {string} leftStyle 
 * @param {string} rightStyle 
 * @param {number} canvasWidth 
 */
function screenBelt(layout, color, zrender, leftStyle, rightStyle, canvasWidth, opacity = 1) {
  let leftColors = color[leftStyle];
  let rightColors = color[rightStyle];

  return new zrender.Rect({
    shape: {
      width: canvasWidth + 20,
      height: layout.beltHeight
    },
    style: {
      fill: new zrender.LinearGradient(
        0, 0, 1, 0,
        [
          {offset:0, color: leftColors[5]},
          {offset:0.08, color: leftColors[4]},
          {offset:0.16, color: leftColors[3]},
          {offset:0.24, color: leftColors[2]},
          {offset:0.32, color: leftColors[1]},
          {offset:0.4, color: leftColors[0]},
          {offset:0.6, color: rightColors[0]},
          {offset:0.68, color: rightColors[1]},
          {offset:0.76, color: rightColors[2]},
          {offset:0.84, color: rightColors[3]},
          {offset:0.92, color: rightColors[4]},
          {offset:1, color: rightColors[5]}
        ]
      ),
      stroke: '#FFF3',
      lineWidth: 6,
      opacity: opacity
    },
    position: [-10, layout.bgMoverOriY],
    z: 20
  });
}

/**
 * @param {Layout} layout
 */
function screenBeltA(layout, zrender, canvasWidth) {
  return new zrender.Rect({
    shape: {
      width: canvasWidth,
      height: layout.beltHeight
    },
    style: {
      fill: new zrender.LinearGradient(
        0, 0, 0, 1,
        [
          {offset:0, color: '#FFF0'},
          {offset:0.09, color: '#FFFA'},
          {offset:0.18, color: '#FFF1'},
          {offset:0.91, color: '#FFF1'},
          {offset:1, color: '#FFF0'}
        ]
      ),
      opacity: 1
    },
    position: [0, layout.bgMoverOriY],
    z: 22
  })
}

/**
 * @param {Layout} layout
 */
function screenBeltFlash(layout, zrender, canvasWidth) {
  return [0, canvasWidth / 2].map(x => {
    return new zrender.Rect({
      shape: {
        width: canvasWidth / 2,
        height: layout.beltHeight
      },
      style: {
        fill: '#FFF',
        opacity: 0
      },
      position: [x, layout.bgMoverOriY],
      z: 22
    });
  });
}

/**
 * 文字
 * @param {Layout} layout
 * @param {string[]} names
 */
function screenBeltText(layout, zrender, canvasWidth, names) {
  return names.map((name, index) => {
    return new zrender.Text({
      style: {
        text: name,
        textAlign: 'center',
        fontWeight: 'bold',
        textVerticalAlign: 'bottom',
        fontSize: 36,
        fontFamily: 'Microsoft YaHei UI',
        textFill: '#FFF',
        textShadowColor: '#000',
        textShadowBlur: 6,
        textShadowOffsetX: (index) ? 3 : -3,
        textShadowOffsetY: 3,
        opacity: 1
      },
      position: [
        canvasWidth * (0.25 + index * 0.5),
        layout.bgMoverOriY + layout.beltHeight * 0.85],
      z: 23
    });
  });
}

/**
 * 带子左右的两个记录时间的背景
 * @param {Layout} layout
 * @param {number} canvasWidth 
 */
function screenBeltRecordChunk(layout, zrender, canvasWidth) {
  return [
    {
      gradX : (layout.beltTimeWidth - 20) / layout.beltTimeWidth,
      gradY : (layout.beltTimeWidth - 20) / layout.beltTimeWidth - 0.1,
      posX : 0,
    },
    {
      gradX : 20 / layout.beltTimeWidth,
      gradY : 20 / layout.beltTimeWidth + 0.1,
      posX : canvasWidth - layout.beltTimeWidth,
    }
  ].map(item => new zrender.Rect({
    shape: {
      width : layout.beltTimeWidth,
      height : layout.beltHeight
    },
    style: {
      fill: new zrender.LinearGradient(
        item.gradX, 1, item.gradY, 0.88,
        [
          {offset:0, color: '#FFF0'},
          {offset:0.07, color: '#FFFA'},
          {offset:0.15, color: '#FFF0'},
          {offset:0.3, color: '#0006'},
          {offset:0.45, color: '#0003'},
          {offset:0.6, color: '#0003'}
        ]
      ),
      stroke: 'none',
      opacity: 0
    },
    position: [item.posX, layout.bgMoverOriY],
    z: 21
  }));
}

/**
 * 带子左右的两个记录时间的文本
 * @param {Layout} layout
 * @param {number} canvasWidth 
 */
function screenBeltRecordText(layout, zrender, canvasWidth) {
  return [
    {
      text : '1',
      posX : layout.beltTimeWidth * 0.5
    },
    {
      text : '2',
      posX : canvasWidth - layout.beltTimeWidth * 0.5,
    }
  ].map(item => new zrender.Text({
    style: {
      text: item.text,
      textAlign: 'center',
      fontWeight: 'bold',
      textVerticalAlign: 'bottom',
      fontSize: 24,
      fontFamily: 'Microsoft YaHei UI',
      textFill: '#FFFA',
      opacity: 0
    },
    position: [
      item.posX, layout.bgMoverOriY + layout.beltHeight * 0.75
    ],
    z: 23
  }));
}

/**
 * 中间那个计时器六角形
 */
function createShapeHexagon(zrender) {
  return zrender.Path.extend({
    type: 'hexagon',
    shape: {
      // 顶部的中心位置
      x: 0,
      y: 0,
      width: 2, // 默认值 ?
      height: 80, // 默认值 ?
      offset: 2
    },
    buildPath: function (path, shape) {
      var x = shape.x;
      var y = shape.y;

      var w = shape.width / 2;
      var h = shape.height;
      var offset = shape.offset;

      path.lineTo(x + w, y);
      path.lineTo(x + w + offset, y + h / 2);
      path.lineTo(x + w, y + h);
      path.lineTo(x - w, y + h);
      path.lineTo(x - w - offset, y + h / 2);
      path.lineTo(x - w, y);
      path.lineTo(x + w, y);
      path.closePath();
    },
    style: {
      stroke: '#FFF',
      lineWidth: 6,
      fill: '#FFF'
    }
  });
}

/**
 * 产生中间那个六角形, 但是还没有添加进去, 仅仅返回
 * buildHexagon()
 * @param {Layout} layout
 * @param {Color} color
 * @param {number} canvasWidth 
 */
function screenBeltHexagon(layout, color, zrender, shapeHexagon, style, canvasWidth, opacity = 1) {
  let colors = color[style];

  return new shapeHexagon({
    shape: {
      width: 378, // 默认值 ?
      offset: 24
    },
    style: {
      fill: new zrender.LinearGradient(
        0, 0, 0, 1,
        [
          {offset:0.3, color: colors[3]},
          {offset:0.7, color: colors[1]}
        ]
      ),
      shadowBlur: 10,
      shadowColor: '#000',
      opacity: opacity
    },
    position: [canvasWidth * 0.5, layout.bgMoverOriY + layout.beltHeight * 0.5 - 40],
    z: 25
  });
};

/**
 * 产生中间那个六角形, 闪光部分
 * buildHexagon()
 * @param {Layout} layout
 * @param {number} canvasWidth 
 */
function screenBeltHexagonFlash(layout, shapeHexagon, canvasWidth) {
  return new shapeHexagon({
    shape: {
      width: 378, // 默认值 ?
      offset: 24
    },
    style: {
      fill: '#FFF',
      lineWidth: 0,
      opacity: 0
    },
    position: [canvasWidth * 0.5, layout.bgMoverOriY + layout.beltHeight * 0.5 - 40],
    z: 26
  });
}

/**
 * 中间的数字
 * @param zrender 
 * @param spriteFigures this.sprites.spriteFigures
 */
function buildFigures(zrender, spriteFigures, ch, x, y, style, isSmall, f) {
  let innerx, innery;
  let clipwidth = 38, clipheight = 39;
  if (ch == ':') {
    innerx = 400; clipwidth = 18;
  } else if (ch == '.') {
    innerx = 420; clipwidth = 18;
  } else { // 数值
    innerx = 40*ch;
  }

  switch (style) {
    case 'dark': innery = 1; break;
    case 'ori': innery = 41; break;
    case 'light': innery = 81; break;
  }

  if (f == null) {
    f = new zrender.Image({
      style: {
        image: spriteFigures,
        x: - innerx,
        y: - innery,
        shadowBlur: 5,
        shadowColor: '#FFFFFF88'
      },
      position: [x, y],
      scale: isSmall ? [0.667, 0.667] : [1, 1],
      z: 100
    });
    var clipPath = new zrender.Rect({
      shape: {
        x: 0,
        y: 0,
        width: clipwidth,
        height: clipheight
      }
    });
    f.setClipPath(clipPath);
  } else {
    f.attr({
      style: {
        opacity: 1,
        x: - innerx,
        y: - innery
      },
      position: [x, y],
      scale: isSmall ? [0.667, 0.667] : [1, 1]
    });
  }
  
  return f;
};



















/* **********
 * 工具方法 *
 ********** */

/**
 * 将时间数值转成文本数组. time 的单位为毫秒
 * 返回的数组格式: 例如 1:15.7, 返回 [7, 5, 1, 1]
 */
function toTimeArray(time) {
  let remain = parseInt(time / 100);
  // ds
  let ds = remain % 10;
  remain = parseInt(remain / 10);

  // s
  let s = remain % 60;
  remain = parseInt(remain / 60);
  if (remain == 0) { // 'ss.d'
    return [ds, s % 10, parseInt(s / 10)];
  }

  // m
  let m = remain % 60;
  remain = parseInt(remain / 60);
  if (remain == 0) {
    if (m < 10) { // 'm.ss.d'
      return [ds, s % 10, parseInt(s / 10), m];
    } else { // 'mm.ss.d'
      return [ds, s % 10, parseInt(s / 10), m % 10, parseInt(m / 10)];
    }
  }

  // h
  let h = remain;
  if (h < 10) { // 'h:mm.ss.d'
    return [ds, s % 10, parseInt(s / 10), m % 10, parseInt(m / 10), h];
  } else { // 'hh:mm.ss.d'
    return [ds, s % 10, parseInt(s / 10), m % 10, parseInt(m / 10), h % 10, parseInt(h / 10)];
  }
}

/**
 * 时间转时间文本
 */
function toTimeText(time) {
  let array = toTimeArray(time);
  let text = '';
  for (let i = 0; i < array.length; i++) {
    switch (i) {
      case 1: text = '.' + text; break;
      case 3: case 5: text = ':' + text; break;
    }
    text = array[i] + text;
  }
  return text;
};


export default createPrinter;
